package com.vdcloud.mcclassroom.filter;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vdcloud.mcclassroom.entity.User;
import com.vdcloud.mcclassroom.service.IUserService;
import com.vdcloud.mcclassroom.util.JwtTokenUtil;
import com.vdcloud.mcclassroom.util.ResponseUtil;
import com.vdcloud.mcclassroom.util.ResultUtil;
import com.vdcloud.mcclassroom.util.SpringUtils;
import com.vdcloud.mcclassroom.vo.UserDetail;
import com.vdcloud.mcclassroom.vo.reqvo.LoginFromVo;
import com.vdcloud.mcclassroom.vo.reqvo.LoginUserVo;
import com.vdcloud.mcclassroom.vo.respvo.LoginSuccessVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;

/**
 * @author songfazhun
 */
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {


    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private IUserService userService;


    private AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }


    /**
     * 登录请求
     *
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            LoginFromVo loginForm = new ObjectMapper().readValue(request.getInputStream(), LoginFromVo.class);
            checkLoginForm(loginForm, response);
            LoginUserVo loginUser = new LoginUserVo();
            BeanUtils.copyProperties(loginForm, loginUser);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(JSONUtil.toJsonStr(loginUser), loginForm.getPassword(), new ArrayList<>()));
        } catch (IOException e) {
            ResponseUtil.write(response, ResultUtil.error("数据读取错误"));
        }
        return null;

    }


    /**
     * 登录城后执行
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        UserDetail userDetail = (UserDetail) authResult.getPrincipal();
        if (jwtTokenUtil == null) {
            jwtTokenUtil = (JwtTokenUtil) SpringUtils.getBean("jwtTokenUtil");
        }
        User user = userService.getLoginUserByUserAccount(userDetail.getUserAccount());
        user.setUserId(userDetail.getUserId());
        user.setLastLoginTime(LocalDateTime.now());
        if (userService == null) {
            userService = (IUserService) SpringUtils.getBean("userService");
        }
        //更新登最近一次录时间
        userService.updateById(user);

        String token = jwtTokenUtil.createToken(userDetail);
        //将token放置请求头返回
        response.addHeader(jwtTokenUtil.getTokenHeader(), jwtTokenUtil.getTokenPrefix() + token);
        LoginSuccessVO loginSuccessVO = new LoginSuccessVO();
        BeanUtils.copyProperties(userDetail, loginSuccessVO);
        ResponseUtil.write(response, ResultUtil.success(loginSuccessVO));

    }


    /**
     * 登录失败
     *
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtil.write(response, ResultUtil.error(failed.getMessage()));
    }


    /**
     * 校验参数
     *
     * @param vo
     * @param response
     */
    private void checkLoginForm(LoginFromVo vo, HttpServletResponse response) {
        if (StringUtils.isEmpty(vo.getUserAccount())) {
            ResponseUtil.write(response, ResultUtil.error("手机号不能为空"));
            return;
        }
        if (StringUtils.isEmpty(vo.getPassword())) {
            ResponseUtil.write(response, ResultUtil.error("密码不能为空"));
            return;
        }
    }

}
